package edu.hawaii.senin.iclouds.basics;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.util.TreeMap;

import org.junit.Before;
import org.junit.Test;

/**
 * Tests simple population routines.
 * 
 * @author Pavel Senin.
 * 
 */
public class TestPopulationSimple {

  private Specie atomH;

  private Specie moleculeH2O;

  private Specie moleculeCO;

  private PopulationSimple pop;

  /**
   * A little fixture before each test.
   * 
   * @throws Exception if error encountered.
   */
  @Before
  public void setUp() throws Exception {
    this.pop = new PopulationSimple();
    this.atomH = new Atom("H", 1L);
    this.moleculeCO = new Molecule("CO", 1L);
    this.moleculeH2O = new Molecule("H2O", 1L);
  }

  /**
   * Test #1.
   * 
   * @throws PopulationException if error encountered.
   */
  @Test
  public void testPopulationSimple1() throws PopulationException {

    this.pop.addSpecie(this.atomH.getName(), this.atomH, 1L);
    this.pop.addSpecie(this.moleculeCO.getName(), this.moleculeCO, 2L);
    this.pop.addSpecie(this.moleculeH2O.getName(), this.moleculeH2O, 7L);
    this.pop.addProduct("HSO4", 11L);

    assertTrue("testing contains", this.pop.contains(this.atomH.getName()));
    assertEquals("testing speciesNum", 4, this.pop.getPopulationSpeciesNum());
    assertEquals("testing getSpecieVolume", 1L, this.pop.getSpecieVolume(this.atomH.getName()));
    assertEquals("testing getPopulationTotalSeize", 21L, this.pop.getPopulationTotalSize());

    this.pop.decrementSpecieAccumulator(this.atomH.getName(), 1L);
    assertFalse("testing contains", this.pop.contains(this.atomH.getName()));

    this.pop.decrementSpecieAccumulator(this.moleculeH2O.getName(), 3L);
    assertEquals("testing speciesNum", 3, this.pop.getPopulationSpeciesNum());
    assertEquals("testing getSpecieVolume", 4L, this.pop
        .getSpecieVolume(this.moleculeH2O.getName()));
    assertEquals("testing getPopulationTotalSeize", 17L, this.pop.getPopulationTotalSize());

    this.pop.incrementSpecieAccumulator(this.moleculeH2O.getName(), 4L);
    assertEquals("testing speciesNum", 3, this.pop.getPopulationSpeciesNum());
    assertEquals("testing getSpecieVolume", 8L, this.pop
        .getSpecieVolume(this.moleculeH2O.getName()));
    assertEquals("testing getPopulationTotalSeize", 21L, this.pop.getPopulationTotalSize());

    this.pop.removeSpecie("HSO4");
    assertFalse("testing contains", this.pop.contains("HSO4"));
    assertEquals("testing speciesNum", 2, this.pop.getPopulationSpeciesNum());
    assertEquals("testing getPopulationTotalSeize", 10L, this.pop.getPopulationTotalSize());

    this.pop.addProduct(this.moleculeCO.getName(), 1L);
    assertEquals("testing speciesNum", 2, this.pop.getPopulationSpeciesNum());
    assertEquals("testing getSpecieVolume", 3L, 
        this.pop.getSpecieVolume(this.moleculeCO.getName()));
    assertEquals("testing getPopulationTotalSeize", 11L, this.pop.getPopulationTotalSize());

    this.pop.addProduct("D", 5L);
    assertEquals("testing speciesNum", 3, this.pop.getPopulationSpeciesNum());
    assertEquals("testing getSpecieVolume", 5L, this.pop.getSpecieVolume("D"));
    assertEquals("testing getPopulationTotalSeize", 16L, this.pop.getPopulationTotalSize());

  }

  /**
   * Tests constructors and simple getters and setters.
   * 
   * @throws PopulationException if went wrong.
   * 
   */
  @Test
  public void testPopulationSimple2() throws PopulationException {

    this.pop.addSpecie(this.atomH.getName(), this.atomH, 1L);
    assertEquals("testing speciesNum", 1, this.pop.getPopulationSpeciesNum());
    assertEquals("testing getSpecieVolume", 1L, this.pop.getSpecieVolume(this.atomH.getName()));
    assertEquals("testing getPopulationTotalSeize", 1L, this.pop.getPopulationTotalSize());

    this.pop.addSpecie(this.moleculeCO.getName(), this.moleculeCO, 2L);
    assertEquals("testing speciesNum", 2, this.pop.getPopulationSpeciesNum());
    assertEquals("testing getSpecieVolume", 1L, this.pop.getSpecieVolume(this.atomH.getName()));
    assertEquals("testing getSpecieVolume", 2L, 
        this.pop.getSpecieVolume(this.moleculeCO.getName()));
    assertEquals("testing getPopulationTotalSeize", 3L, this.pop.getPopulationTotalSize());

    this.pop.addSpecie(this.moleculeH2O.getName(), this.moleculeH2O, 7L);
    assertEquals("testing speciesNum", 3, this.pop.getPopulationSpeciesNum());
    assertEquals("testing getSpecieVolume", 7L, this.pop
        .getSpecieVolume(this.moleculeH2O.getName()));
    assertEquals("testing getPopulationTotalSeize", 10L, this.pop.getPopulationTotalSize());

    this.pop.addProduct("HSO4", 11L);
    assertEquals("testing speciesNum", 4, this.pop.getPopulationSpeciesNum());
    assertEquals("testing getSpecieVolume", 11L, this.pop.getSpecieVolume("HSO4"));
    assertEquals("testing getPopulationTotalSeize", 21L, this.pop.getPopulationTotalSize());

    assertTrue("testing contains", this.pop.contains(this.atomH.getName()));
    assertTrue("testing contains", this.pop.contains(this.moleculeCO.getName()));
    assertTrue("testing contains", this.pop.contains(this.moleculeH2O.getName()));
    assertTrue("testing contains", this.pop.contains("HSO4"));
    assertFalse("testing contains", this.pop.contains("MNSO4"));

  }

  /**
   * Tests second constructor.
   * 
   * @throws PopulationException if went wrong.
   * 
   */
  @Test
  public void testPopulationSimpleTreeMapOfStringSpecie() throws PopulationException {
    TreeMap<String, Specie> tMap = new TreeMap<String, Specie>();
    tMap.put("HSO4", new Molecule("HSO4", 11L));
    tMap.put(this.atomH.getName(), this.atomH);

    this.pop = new PopulationSimple(tMap);

    assertEquals("testing speciesNum", 2, this.pop.getPopulationSpeciesNum());
    assertEquals("testing getSpecieVolume", 1L, this.pop.getSpecieVolume(this.atomH.getName()));
    assertEquals("testing getSpecieVolume", 11L, this.pop.getSpecieVolume("HSO4"));
    assertEquals("testing getPopulationTotalSeize", 12L, this.pop.getPopulationTotalSize());

  }

}
